﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using matrix = Microsoft.Xna.Framework.Matrix;

namespace XnaCanvas {
    public class XObj2 : XObject {
        public override void Present() {
            PersentX();
        }
        void PersentA() {
            effect.World = World;
            effect.View = xsence.viewer;
            effect.Projection = xsence.projection;
            effect.DiffuseColor = xsence.diffuseColor.ToVector3();
            effect.Alpha = xsence.diffuseColor.A / 255.0f;
            XSence.Device.SetVertexBuffer(vbuffer);
            foreach (var pass in effect.CurrentTechnique.Passes) {
                pass.Apply();
                XSence.Device.DrawPrimitives(base.PrimitivType, 0, primitiveCount);
            }
        }
        void PersentB() {
            effect.World = World;
            effect.View = xsence.viewer;
            effect.Projection = xsence.projection;
            effect.DiffuseColor = xsence.diffuseColor.ToVector3();
            effect.Alpha = xsence.diffuseColor.A / 255.0f;
            XSence.Device.SetVertexBuffer(vbuffer);
            XSence.Device.Indices = ibuffer;
            foreach (var pass in effect.CurrentTechnique.Passes) {
                pass.Apply();
                XSence.Device.DrawIndexedPrimitives(PrimitivType, 0, 0, vertices.Count, 0, primitiveCount);
            }
        }
        Action PersentX;
        public XObj2(PrimitiveType pt = PrimitiveType.LineList, bool IsIndexPersent = false) {
            vertices = new List<VertexPositionNormalColor>();
            indices = new List<ushort>();
            base.PrimitivType = pt;
            //this.isDynamicIV = true;
            if (IsIndexPersent) {
                PersentX = PersentB;
            } else {
                PersentX = PersentA;
            }
        }
        public void AddIndex2D(int i, int j) {
            indices.Add((ushort)i);
            indices.Add((ushort)j);
        }
        #region base sharp
        public void LoadCircleBorder(float radius = 1, int count = 32) {
            ClearBuffer();
            PersentX = PersentA;
            for (int i = 0; i < count; i++) {
                var angle = i * MathHelper.TwoPi / count;
                var angle2 = (i + 1) * MathHelper.TwoPi / count;
                var v = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
                var v3 = new Vector2((float)Math.Cos(angle2), (float)Math.Sin(angle2));
                var v2 = v * radius;
                var v4 = v3 * radius;
                AddVertex(v2, new Vector3(v.X, v.Y, 0));
                AddVertex(v4, new Vector3(v4.X, v4.Y, 0));
            }
            base.PrimitivType = PrimitiveType.LineList;
            SetData();
        }
        public void LoadCircleBorderByIndex(float radius = 1, int count = 32) {
            ClearBuffer();
            PersentX = PersentB;
            for (int i = 0; i < count; i++) {
                var angle = i * MathHelper.TwoPi / count;
                var v = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
                var v2 = v * radius;
                AddVertex(v2, new Vector3(v.X, v.Y, 0));
                AddIndex(i);
                AddIndex((i + 1) % count);
            }
            base.PrimitivType = PrimitiveType.LineList;
            SetData();
        }
        public void LoadCircle(float radius = 1, int count = 32) {
            ClearBuffer();
            PersentX = PersentA;
            for (int i = 0; i < count; i++) {
                var angle = i * MathHelper.TwoPi / count;
                var angle2 = (i + 1) * MathHelper.TwoPi / count;
                var v = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
                var v3 = new Vector2((float)Math.Cos(angle2), (float)Math.Sin(angle2));
                var v2 = v * radius;
                var v4 = v3 * radius;
                AddVertex(v2, new Vector3(v.X, v.Y, 0));
                AddVertex(Vector3.Zero, Vector3.Zero);
                AddVertex(v4, new Vector3(v4.X, v4.Y, 0));
            }
            base.PrimitivType = PrimitiveType.TriangleList;
            SetData();
        }
        public void LoadCircleByIndex(float radius = 1, int count = 32) {
            ClearBuffer();
            PersentX = PersentB;
            for (int i = 0; i < count; i++) {
                var angle = i * MathHelper.TwoPi / count;
                var v = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
                var v2 = v * radius;
                AddVertex(v2, new Vector3(v.X, v.Y, 0));
                AddIndex((i + 2) % count);
                AddIndex((i + 1) % count);
                AddIndex(0);
            }
            base.PrimitivType = PrimitiveType.TriangleList;
            SetData();
        }
        public void LoadEllipseBorder(float smallRadius = .8f, float bigRadius = 1.5f, int count = 32) {
            ClearBuffer();
            PersentX = PersentA;
            for (int i = 0; i < count; i++) {
                var angle = i * MathHelper.TwoPi / count;
                var angle2 = (i + 1) * MathHelper.TwoPi / count;
                var v = new Vector2((float)Math.Cos(angle) * bigRadius, (float)Math.Sin(angle) * smallRadius);
                var v2 = new Vector2((float)Math.Cos(angle2) * bigRadius, (float)Math.Sin(angle2) * smallRadius);
                AddVertex(v, new Vector3(v.X, v.Y, 0));
                AddVertex(v2, new Vector3(v2.X, v2.Y, 0));
            }
            base.PrimitivType = PrimitiveType.LineList;
            SetData();
        }
        public void LoadEllipseBorderByIndex(float smallRadius = .8f, float bigRadius = 1.5f, int count = 32) {
            ClearBuffer();
            PersentX = PersentB;
            for (int i = 0; i < count; i++) {
                var angle = i * MathHelper.TwoPi / count;
                var v = new Vector2((float)Math.Cos(angle) * bigRadius, (float)Math.Sin(angle) * smallRadius);
                AddVertex(v, new Vector3(v.X, v.Y, 0));
                //AddVertex(v2, new Vector3(v2.X, v2.Y, 0));
                AddIndex(i);
                AddIndex((i + 1) % count);
            }
            base.PrimitivType = PrimitiveType.LineList;
            SetData();
        }
        public void LoadEllipse(float smallRadius = .8f, float bigRadius = 1.5f, int count = 32) {
            ClearBuffer();
            PersentX = PersentA;
            for (int i = 0; i < count; i++) {
                var angle = i * MathHelper.TwoPi / count;
                var angle2 = (i + 1) * MathHelper.TwoPi / count;
                var v = new Vector2((float)Math.Cos(angle) * bigRadius, (float)Math.Sin(angle) * smallRadius);
                var v2 = new Vector2((float)Math.Cos(angle2) * bigRadius, (float)Math.Sin(angle2) * smallRadius);

                AddVertex(v, new Vector3(v.X, v.Y, 0));
                AddVertex(Vector3.Zero, Vector3.Zero);
                AddVertex(v2, new Vector3(v2.X, v2.Y, 0));
            }
            base.PrimitivType = PrimitiveType.TriangleList;
            SetData();
        }
        public void LoadEllipseByIndex(float smallRadius = .8f, float bigRadius = 1.5f, int count = 32) {
            ClearBuffer();
            PersentX = PersentB;
            for (int i = 0; i < count; i++) {
                var angle = i * MathHelper.TwoPi / count;
                var v = new Vector2((float)Math.Cos(angle) * bigRadius, (float)Math.Sin(angle) * smallRadius);

                AddVertex(v, new Vector3(v.X, v.Y, 0));
                //AddVertex(Vector3.Zero, Vector3.Zero);
                //AddVertex(v2, new Vector3(v2.X, v2.Y, 0));
                AddIndex(i);
                AddIndex(count);
                AddIndex((i + 1) % count);
            }
            AddVertex(Vector3.Zero, Vector3.Zero);
            base.PrimitivType = PrimitiveType.TriangleList;
            SetData();
        }
        public void LoadRectangleBorder(float width = 1, float height = 1) {
            ClearBuffer();
            var v1 = new Vector2(width / 2, height / 2);
            var v2 = new Vector2(-width / 2, height / 2);
            var v3 = new Vector2(-width / 2, -height / 2);
            var v4 = new Vector2(width / 2, -height / 2);
            AddVertex(v1, Vector3.Zero);
            AddVertex(v2, Vector3.Zero);
            AddVertex(v2, Vector3.Zero);
            AddVertex(v3, Vector3.Zero);
            //
            AddVertex(v3, Vector3.Zero);
            AddVertex(v4, Vector3.Zero);
            AddVertex(v4, Vector3.Zero);
            AddVertex(v1, Vector3.Zero);
            base.PrimitivType = PrimitiveType.LineList;
            SetData();
        }
        public void LoadRectangleBorderByIndex(float width = 1, float height = 1) {
            ClearBuffer();
            PersentX = PersentB;
            var v1 = new Vector2(width / 2, height / 2);
            var v2 = new Vector2(-width / 2, height / 2);
            var v3 = new Vector2(-width / 2, -height / 2);
            var v4 = new Vector2(width / 2, -height / 2);
            AddVertex(v1, Vector3.Zero);
            AddVertex(v2, Vector3.Zero);
            AddVertex(v3, Vector3.Zero);
            AddVertex(v4, Vector3.Zero);
            //
            AddIndex(0);
            AddIndex(1);
            AddIndex(1);
            AddIndex(2);
            AddIndex(2);
            AddIndex(3);
            AddIndex(3);
            AddIndex(0);
            base.PrimitivType = PrimitiveType.LineList;
            SetData();
        }
        public void LoadRectangle(float width = 1, float height = 1) {
            ClearBuffer();
            var v1 = new Vector2(width / 2, height / 2);
            var v2 = new Vector2(-width / 2, height / 2);
            var v3 = new Vector2(-width / 2, -height / 2);
            var v4 = new Vector2(width / 2, -height / 2);
            AddVertex(v1, Vector3.Zero);
            AddVertex(v4, Vector3.Zero);
            AddVertex(v3, Vector3.Zero);
            //
            AddVertex(v1, Vector3.Zero);
            AddVertex(v3, Vector3.Zero);
            AddVertex(v2, Vector3.Zero);
            base.PrimitivType = PrimitiveType.TriangleList;
            SetData();
        }
        public void LoadRectangleByIndex(float width = 1, float height = 1) {
            ClearBuffer();
            PersentX = PersentB;
            var v1 = new Vector2(width / 2, height / 2);
            var v2 = new Vector2(-width / 2, height / 2);
            var v3 = new Vector2(-width / 2, -height / 2);
            var v4 = new Vector2(width / 2, -height / 2);
            AddVertex(v1, Vector3.Zero);
            AddVertex(v2, Vector3.Zero);
            AddVertex(v3, Vector3.Zero);
            AddVertex(v4, Vector3.Zero);
            AddIndex(0);
            AddIndex(3);
            AddIndex(2);
            AddIndex(0);
            AddIndex(2);
            AddIndex(1);
            base.PrimitivType = PrimitiveType.TriangleList;
            SetData();
        }
        public void LoadPolygonBorder(float radius = 1, int sideCount = 5) {
            ClearBuffer();
            for (int i = 0; i < sideCount; i++) {
                var angle = i * MathHelper.TwoPi / sideCount;
                var angle2 = (i + 1) * MathHelper.TwoPi / sideCount;
                var v = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
                var v3 = new Vector2((float)Math.Cos(angle2), (float)Math.Sin(angle2));
                var v2 = v * radius;
                var v4 = v3 * radius;
                AddVertex(v2, Vector3.Zero);
                AddVertex(v4, Vector3.Zero);
            }
            base.PrimitivType = PrimitiveType.LineList;
            SetData();
        }
        public void LoadPolygonBorderByIndex(float radius = 1, int sideCount = 5) {
            ClearBuffer();
            PersentX = PersentB;
            for (int i = 0; i < sideCount; i++) {
                var angle = i * MathHelper.TwoPi / sideCount;
                var v = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
                var v2 = v * radius;
                AddVertex(v2, Vector3.Zero);
                AddIndex(i);
                AddIndex((i + 1) % sideCount);
            }
            base.PrimitivType = PrimitiveType.LineList;
            SetData();
        }
        public void LoadPolygon(float radius = 1, int sideCount = 5) {
            ClearBuffer();
            for (int i = 0; i < sideCount; i++) {
                var angle = i * MathHelper.TwoPi / sideCount;
                var angle2 = (i + 1) * MathHelper.TwoPi / sideCount;
                var v = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
                var v3 = new Vector2((float)Math.Cos(angle2), (float)Math.Sin(angle2));
                var v2 = v * radius;
                var v4 = v3 * radius;
                AddVertex(v2, Vector3.Zero);
                AddVertex(Vector3.Zero, Vector3.Zero);
                AddVertex(v4, Vector3.Zero);
            }
            base.PrimitivType = PrimitiveType.TriangleList;
            SetData();
        }
        public void LoadPolygonByIndex(float radius = 1, int sideCount = 5) {
            ClearBuffer();
            PersentX = PersentB;
            for (int i = 0; i < sideCount; i++) {
                var angle = i * MathHelper.TwoPi / sideCount;
                var v = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle));
                var v2 = v * radius;
                AddVertex(v2, Vector3.Zero);
                AddIndex((i + 2) % sideCount);
                AddIndex((i + 1) % sideCount);
                AddIndex(0);
            }
            base.PrimitivType = PrimitiveType.TriangleList;
            SetData();
        }
        public void LoadTrangleBorder(Vector2 a, Vector2 b, Vector2 c) {
            ClearBuffer();
            AddVertex(a, Vector3.Zero);
            AddVertex(b, Vector3.Zero);
            AddVertex(b, Vector3.Zero);
            AddVertex(c, Vector3.Zero);
            AddVertex(c, Vector3.Zero);
            AddVertex(a, Vector3.Zero);
            base.PrimitivType = PrimitiveType.LineList;
            SetData();
        }
        public void LoadTrangleBorderByIndex(Vector2 a, Vector2 b, Vector2 c) {
            ClearBuffer();
            PersentX = PersentB;
            AddVertex(a, Vector3.Zero);
            AddVertex(b, Vector3.Zero);
            AddVertex(c, Vector3.Zero);
            AddIndex(0);
            AddIndex(1);
            AddIndex(1);
            AddIndex(2);
            AddIndex(2);
            AddIndex(0);
            base.PrimitivType = PrimitiveType.LineList;
            SetData();
        }
        public void LoadTrangle(Vector2 a, Vector2 b, Vector2 c) {
            ClearBuffer();
            AddVertex(a, Vector3.Zero);
            AddVertex(b, Vector3.Zero);
            AddVertex(c, Vector3.Zero);
            base.PrimitivType = PrimitiveType.TriangleList;
            SetData();
        }
        public void LoadLine(Vector2 a, Vector2 b) {
            ClearBuffer();
            AddVertex(a, Vector3.Zero);
            AddVertex(b, Vector3.Zero);
            base.PrimitivType = PrimitiveType.LineList;
            SetData();
        }
        //public void LoadFunc(
        #endregion
    }
}
